---
title: Custom Plan and Apply
description: Customize your Terraform Plan and Apply workflows
---

import { Steps } from '@astrojs/starlight/components';
import { Tabs, TabItem } from '@astrojs/starlight/components';

Terrateam's custom plan and apply steps feature allows you to extend your Terraform workflows with additional automation steps. This feature is particularly useful when you need to:

- Perform pre-validation checks before applying infrastructure changes
- Run security and compliance scans
- Integrate with external monitoring or notification systems

## Configuring Custom Steps

To configure custom steps in your workflow, modify your Terrateam configuration file (`.terrateam/config.yml`):

```yaml
workflows:
  - tag_query: "dir:prod"
    plan:
      - type: init
      - type: run
        cmd: ['${TERRATEAM_ROOT}/scripts/pre-plan.sh']
      - type: plan
      - type: run
        cmd: ['${TERRATEAM_ROOT}/scripts/post-plan.sh']
    apply:
      - type: init
      - type: run
        cmd: ['${TERRATEAM_ROOT}/scripts/pre-apply.sh']
      - type: apply
      - type: run
        cmd: ['${TERRATEAM_ROOT}/scripts/post-apply.sh']
```

:::note[What is TERRATEAM_ROOT?]
The `TERRATEAM_ROOT` environment variable points to the absolute path of your checked-out repository.
:::

## Custom Step Types

Terrateam supports the following types of steps in workflows:

### Run

The `run` step executes a command or script:

```yaml
- type: run
  cmd: ['${TERRATEAM_ROOT}/scripts/my-script.sh']
```
- `cmd`: Command to execute (array of strings)

:::tip
See [Run Step Options](/reference/configuration/workflows#run) for additional options.
:::

### Env

The `env` step sets environment variables for subsequent steps:

```yaml
- type: env
  name: MY_VAR
  cmd: ['echo', 'my-value']
```
- `name`: Name of environment variable to set
- `cmd`: Command that generates the variable value

:::tip
See [Env Step Options](/reference/configuration/workflows#env) for additional options.
:::

### OIDC

The `oidc` step handles cloud provider authentication using OpenID Connect:

<Tabs>
  <TabItem label="AWS">
    ```yaml
    - type: oidc
      provider: aws
      role_arn: arn:aws:iam::123456789012:role/terraform-role
      region: us-west-2
    ```
  </TabItem>
  <TabItem label="GCP">
    ```yaml
    - type: oidc
      provider: gcp
      project_id: your-project-id
      workload_identity_provider: projects/123456/locations/global/workloadIdentityPools/my-pool/providers/my-provider
      service_account: my-service-account@my-project.iam.gserviceaccount.com
    ```
  </TabItem>
</Tabs>

:::tip
See [Workflows](/reference/configuration/workflows#oidc) for detailed OIDC configuration.
:::

## Example Workflow

This example demonstrates how the [above configuration](#configuring-custom-steps) works in practice:

<Steps>
1. Open a pull request with Terraform code changes in the `prod` directory.

2. Terrateam executes the custom plan workflow:
   ###### `pre-plan.sh` is executed
   ###### `terraform init` is executed
   ###### `terraform plan` is executed
   ###### `post-plan.sh` is executed

3. Review the plan output and collaborate with your team.

4. After approval and merge, Terrateam executes the custom apply workflow:
   ###### `pre-apply.sh` is executed
   ###### `terraform init` is executed
   ###### `terraform apply` is executed
   ###### `post-apply.sh` is executed

5. Terrateam comments on the pull request with the apply results.
</Steps>

## Considerations
- Scripts in custom steps can access sensitive information - ensure proper security measures and avoid exposing sensitive data in logs
- Failed custom steps abort the workflow [by default (see `ignore_errors`)](/reference/configuration/workflows/#run)- Terrateam comments the error details on the pull request
- Use [Dirs](/reference/configuration/dirs) and [Tags](/advanced-workflows/tags) to target specific directories with custom automation
- Steps execute sequentially in the order defined - ensure dependencies are handled properly

## Best Practices
- Use [Hooks](/reference/configuration/hooks) to run custom steps before or after specific operation, such as plan or apply.
- Pass configuration through environment variables instead of hardcoding
- Include proper error handling and logging in custom scripts
- Document script dependencies and requirements
- Keep scripts focused on single responsibilities
- Use version control for custom scripts alongside infrastructure code
